package com.treeliked.netdiskdemo.interceptor;

import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.treeliked.netdiskdemo.util.AuthConstant;
import com.treeliked.netdiskdemo.util.CookieUtils;
import com.treeliked.netdiskdemo.util.JwtUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 对 file & folder 操作的api 进行jwt验证
 *
 * @author lqs2
 * @date 2018-12-12, Wed
 */
public class ApiInterceptor implements HandlerInterceptor {

    /**
     * 用来保存token中用户id的key
     */
    private static final String KEY_OF_USER_ID = "UID";

    /**
     * 请求api未携带token返回的信息
     */
    private static final String ILLEGAL_REQUEST_WITH_NO_TOKEN = "非法请求";

    /**
     * 请求api token失效
     */
    private static final String ILLEGAL_REQUEST_WITH_TOKEN_EXPIRED = "会话超时，请重新登录";


    /**
     * payload 指定的key 不存在
     */
    private static final String ILLEGAL_REQUEST_WITH_INVALID_CLAIM = "非法TOKEN";

    /**
     * 日志打印
     */
    private static final Logger log = LoggerFactory.getLogger(ApiInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);

        // 如果请求头中不包含AUTHORIZATION，从COOKIE中检查是否存在TID
        if (authorizationHeader == null) {
            authorizationHeader = CookieUtils.getCookieByName(request, AuthConstant.AUTH_KEY_OF_TOKEN_ID);
        }

        if (StringUtils.isBlank(authorizationHeader)) {
            // 没有通过验证，返回401
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ILLEGAL_REQUEST_WITH_NO_TOKEN);
            return false;
        }

        String token = JwtUtils.getTokenFromAuthHeader(authorizationHeader);

        try {
            String uId = JwtUtils.getTokenValueByKey(token, KEY_OF_USER_ID).asString();
            String uid = request.getParameter("uId");
            // 判断token中的 user id 和 url中的id 参数 是否相同，如果不同，则非法请求
            if (!StringUtils.equals(uId, uid)) {
                log.info("TOKEN_USER_ID: {}", uId);
                log.info("REQUEST_USER_ID: {}", uid);
                log.info("请求 {} 被拦截", request.getRequestURL());
                return false;
            }
            log.info("用户ID：{}，访问路径：{}", uId, request.getRequestURL());
        } catch (JWTVerificationException e) {
            log.error("", e);
            if (e instanceof TokenExpiredException) {
                // token 失效
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ILLEGAL_REQUEST_WITH_TOKEN_EXPIRED);
                return false;
            }
            if (e instanceof InvalidClaimException) {
                // 指定的key不存在
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ILLEGAL_REQUEST_WITH_INVALID_CLAIM);
                return false;
            }
        }
        return true;
    }
}
